using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Pavilion
{
    public abstract class NodeBase
    {
        public event NameChangedDelegate NameChanged;
        public event Action<NodeBase, Link> LinkAdded;

        public List<Link> LinkCollection { get; private set; }
        public List<GameData> GameDataCollection { get { return (_gameDataCollection == null) ? _gameDataCollection = new List<GameData>() : _gameDataCollection; } } 
        public ContainerNode ParentContainer { get; set; }
        private string _name;
        private List<GameData> _gameDataCollection;

        public string Name
        {
            get { return _name; }
            set
            {
                if (_name == value)
                    return;

                string oldName = _name;
                _name = value;
                OnNameChanged(oldName, _name);
            }
        }

        public NodeBase()
        {            
            LinkCollection = new List<Link>();
        }

        public virtual void Dispose()
        {
            LinkCollection.Clear();

            ParentContainer = null;
        }

        public Link AddLink(NodeBase node, IEnumerable<ILock> lockList, OpenCriteria openCriteria)
        {
            foreach (Link linkItem in LinkCollection)
            {
                if (linkItem.EndingNode == node)
                    return null;
            }

            Link link = new Link(this, node, lockList, openCriteria);
            link.Disposed += new EventHandler(LinkNode_Disposed);

            LinkCollection.Add(link);
            OnLinkAdded(link);

            return link;
        }

        public void RemoveLink(Link link)
        {
            link.Disposed -= new EventHandler(LinkNode_Disposed);

            LinkCollection.Remove(link);
        }

        /// <summary>
        /// Removes all the links from this node.
        /// </summary>
        /// <param name="node">The specific linked node to be removed.</param>
        public void RemoveLinksByNode(NodeBase node)
        {
            for (int i = 0; i < LinkCollection.Count; i++)
            {
                if (LinkCollection[i].EndingNode == node || LinkCollection[i].StartingNode == node)
                {
                    RemoveLink(LinkCollection[i]);
                    i--;
                }
            }
        }

        internal void UpdateGameToolData(GameItem gameItem)
        {
            if (_gameDataCollection == null)
                return;

            foreach (GameData gameData in GameDataCollection)
                gameItem.ObtainTool(gameData.DataInfo.ToolName).UpdateData(gameData);
        }

        public override string ToString()
        {
            return Name;
        }

        private void OnNameChanged(string oldName, string newName)
        {
            if (NameChanged != null)
                NameChanged(oldName, newName);
        }

        private void OnLinkAdded(Link link)
        {
            if (LinkAdded != null)
                LinkAdded(this, link);
        }

        private void LinkNode_Disposed(object sender, EventArgs e)
        {
            RemoveLink((Link)sender);
        }
    }
}
